#include "comm/znx_log.h"
#include "event/znx_proc.h"
#include "conf/znx_core_conf.h"
#include "conf/znx_http_site_conf.h"
#include "event/znx_worker_proc.h"

#if (ZNX_EXP_HTTP_MODULE)

#include "exp_http/exp_http.h"

void test_exp_http_module()
{
    ZNX_DEF_LOG_DEBUG(NULL, "test exp http module");

    znx_exp_http_conf_t         *exp_conf;
    exp_conf = znx_http_get_main_module_conf(exp_http_module);
    if (exp_conf == NULL) {
        ZNX_DEF_LOG_FATAL(NULL, "not found exp conf");
    }

    if (exp_conf->e1 != 123) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 123, but got %d", exp_conf->e1);
    }

    if (exp_conf->e2.len != 8 ||
        znx_strncmp(exp_conf->e2.data, "exp_test", 8) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect exp_test, but got %v", &exp_conf->e2);
    }

    if (!exp_conf->e3) {
        ZNX_DEF_LOG_FATAL(NULL, "expect true, but got false");
    }

    ZNX_DEF_LOG_DEBUG(NULL, "exp_http_module test success");
}


#endif


static void test_http_site_conf_parse()
{
    znx_http_site_conf_t *site_conf = znx_http_site_conf_create();
    znx_str_t servername = ZNX_STRING("site_exp");
    if (!znx_http_site_conf_parse(site_conf, "/tmp/http/sites_enabled/www.a.com.yaml", &servername)) {
        ZNX_DEF_LOG_FATAL(NULL, "%v", &site_conf->err);
    }

    if (site_conf->server_core_conf != g_http_main_conf->server_core_conf) {
        ZNX_DEF_LOG_FATAL(NULL,
            "expect site_conf->server_core_conf == g_http_main_conf->server_core_conf");
    }

    if (site_conf->proxy_core_conf->read_request_header_timeout_ms != 300) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 300, but got %d",
            site_conf->proxy_core_conf->read_request_header_timeout_ms);
    }

    if (site_conf->proxy_core_conf->request_header_buf_size != 8000) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 8000, but got %d",
            site_conf->proxy_core_conf->request_header_buf_size);
    }

    if (site_conf->proxy_core_conf->max_request_header_size !=
        g_http_main_conf->proxy_core_conf->max_request_header_size)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect %d, but got %d",
            g_http_main_conf->proxy_core_conf->max_request_header_size,
            site_conf->proxy_core_conf->max_request_header_size);
    }

#if (ZNX_EXP_HTTP_MODULE)
    znx_exp_http_conf_t             *pre_exp_http_conf;
    znx_exp_http_conf_t             *exp_http_conf;
    exp_http_conf = znx_http_get_site_module_conf(site_conf, exp_http_module);
    if (exp_http_conf->e1 != 456) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 456, but got %d", exp_http_conf->e1);
    }

    if (exp_http_conf->e2.len != 8 ||
        znx_strncmp(exp_http_conf->e2.data, "exp_test", 8) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect exp_test, but got %v", &exp_http_conf->e2);
    }

    if (!exp_http_conf->e3) {
        ZNX_DEF_LOG_FATAL(NULL, "expect true, but got false");
    }
#endif

    if (site_conf->addr_sites->nelts != 2) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2, but got %d", site_conf->addr_sites->nelts);
    }

    znx_http_addr_site_conf_t       *addr_site;
    znx_str_t                       *str;
    znx_address_t                   *address;
    znx_http_loc_conf_t             *loc_conf;

    addr_site = site_conf->addr_sites->elts;

#if (ZNX_EXP_HTTP_MODULE)
    exp_http_conf = znx_http_get_addr_site_module_conf(addr_site, exp_http_module);
    if (exp_http_conf->e1 != 789) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 456, but got %d", exp_http_conf->e1);
    }

    if (exp_http_conf->e2.len != 8 ||
        znx_strncmp(exp_http_conf->e2.data, "exp_test", 8) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect exp_test, but got %v", &exp_http_conf->e2);
    }

    if (!exp_http_conf->e3) {
        ZNX_DEF_LOG_FATAL(NULL, "expect true, but got false");
    }
#endif

    if (addr_site->address_names->nelts != 2) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2, but got %d", addr_site->address_names->nelts);
    }

    str = addr_site->address_names->elts;
    if (str->len != 5 || znx_strncmp(str->data, ":8888", 5) != 0) {
        ZNX_DEF_LOG_FATAL(NULL, "expect :8888, but got %v", str);
    }

    str = str+1;
    if (str->len != 9 || znx_strncmp(str->data, "[::]:8888", 9) != 0) {
        ZNX_DEF_LOG_FATAL(NULL, "expect [::]:8888, but got %v", str);
    }

    int             tmp_port;
    znx_address_t   tmp_address;

    bzero(&tmp_address, sizeof(znx_address_t));
    znx_address_parser((u_char *)":8888", 5, &tmp_address, &tmp_port);
    address = addr_site->address_arr->elts;
    if (znx_memcmp(address, &tmp_address, sizeof(znx_address_t)) != 0) {
        ZNX_DEF_LOG_FATAL(NULL, "expect address == tmp_address");
    }

    bzero(&tmp_address, sizeof(znx_address_t));
    znx_address_parser((u_char *)"[::]:8888", 9, &tmp_address, &tmp_port);
    address = address+1;
    if (znx_memcmp(address, &tmp_address, sizeof(znx_address_t)) != 0) {
        ZNX_DEF_LOG_FATAL(NULL, "expect address == tmp_address");
    }

    if (addr_site->server_core_conf->read_request_header_timeout_ms != 500) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 500, but got %d",
            addr_site->server_core_conf->read_request_header_timeout_ms);
    }

    if (addr_site->server_core_conf->request_header_buf_size !=
        site_conf->server_core_conf->request_header_buf_size)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect %d, but got %d",
            site_conf->server_core_conf->request_header_buf_size,
            addr_site->server_core_conf->request_header_buf_size);
    }

    if (addr_site->server_core_conf->max_request_header_size !=
        site_conf->server_core_conf->max_request_header_size)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect %d, but got %d",
            site_conf->server_core_conf->max_request_header_size,
            addr_site->server_core_conf->max_request_header_size);
    }

    if (addr_site->proxy_core_conf != site_conf->proxy_core_conf) {
        ZNX_DEF_LOG_FATAL(NULL,
            "expect addr_site->proxy_core_conf == site_conf->proxy_core_conf");
    }

    if (addr_site->loc_confs->nelts != 2) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2, but got %d",
            addr_site->loc_confs->nelts);
    }

    loc_conf = addr_site->loc_confs->elts;

#if (ZNX_EXP_HTTP_MODULE)
    exp_http_conf = znx_http_get_loc_module_conf(loc_conf, exp_http_module);
    pre_exp_http_conf = znx_http_get_addr_site_module_conf(addr_site, exp_http_module);
    if (exp_http_conf != pre_exp_http_conf) {
        ZNX_DEF_LOG_FATAL(NULL, "exp_http_conf == pre_exp_http_conf");
    }
#endif

    if (loc_conf->type != 1) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 1, but got %d", loc_conf->type);
    }

    if (loc_conf->path.len != 3 ||
        znx_strncmp(loc_conf->path.data, "/a/", 3) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect /a/, but got %v", &loc_conf->path);
    }

    loc_conf = loc_conf+1;

#if (ZNX_EXP_HTTP_MODULE)
    exp_http_conf = znx_http_get_loc_module_conf(loc_conf, exp_http_module);
    if (exp_http_conf->e1 != 789) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 456, but got %d", exp_http_conf->e1);
    }

    if (exp_http_conf->e2.len != 13 ||
        znx_strncmp(exp_http_conf->e2.data, "exp_test_path", 13) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect exp_test_path, but got %v", &exp_http_conf->e2);
    }

    if (!exp_http_conf->e3) {
        ZNX_DEF_LOG_FATAL(NULL, "expect true, but got false");
    }
#endif

    if (loc_conf->type != 1) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 1, but got %d", loc_conf->type);
    }

    if (loc_conf->path.len != 1 ||
        znx_strncmp(loc_conf->path.data, "/", 1) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect /, but got %v", &loc_conf->path);
    }

    addr_site = addr_site+1;

#if (ZNX_EXP_HTTP_MODULE)
    exp_http_conf = znx_http_get_addr_site_module_conf(addr_site, exp_http_module);
    pre_exp_http_conf = znx_http_get_site_module_conf(site_conf, exp_http_module);
    if (exp_http_conf != pre_exp_http_conf) {
        ZNX_DEF_LOG_FATAL(NULL, "exp_http_conf == pre_exp_http_conf");
    }
#endif

    // it's default addr_site conf.
    if (addr_site->address_names != NULL) {
        ZNX_DEF_LOG_FATAL(NULL, "expect NULL");
    }

    if (addr_site->server_core_conf != site_conf->server_core_conf) {
        ZNX_DEF_LOG_FATAL(NULL,
            "expect addr_site->server_core_conf == site_conf->server_core_conf");
    }

    if (addr_site->proxy_core_conf->read_request_header_timeout_ms != 600) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 600, but got %d",
            addr_site->proxy_core_conf->read_request_header_timeout_ms);
    }

    if (addr_site->proxy_core_conf->request_header_buf_size != 
        site_conf->proxy_core_conf->request_header_buf_size)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect %d, but got %d",
            site_conf->proxy_core_conf->request_header_buf_size,
            addr_site->proxy_core_conf->request_header_buf_size);
    }

    if (addr_site->proxy_core_conf->max_request_header_size !=
        site_conf->proxy_core_conf->max_request_header_size)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect %d, but got %d",
            site_conf->proxy_core_conf->max_request_header_size,
            addr_site->proxy_core_conf->max_request_header_size);
    }

    if (addr_site->loc_confs->nelts != 1) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 1, but got %d",
            addr_site->loc_confs->nelts);
    }

    loc_conf = addr_site->loc_confs->elts;

#if (ZNX_EXP_HTTP_MODULE)
    exp_http_conf = znx_http_get_loc_module_conf(loc_conf, exp_http_module);
    pre_exp_http_conf = znx_http_get_addr_site_module_conf(addr_site, exp_http_module);
    if (exp_http_conf != pre_exp_http_conf) {
        ZNX_DEF_LOG_FATAL(NULL, "exp_http_conf == pre_exp_http_conf");
    }
#endif


    if (loc_conf->type != 2) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2, but got %d",
            loc_conf->type);
    }

    if (loc_conf->path.len != 5 ||
        znx_strncmp(loc_conf->path.data, "/aaaa", 5) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect /aaaa, but got %v",
            &loc_conf->path);
    }


    znx_http_site_conf_free(site_conf);
}


int main()
{
    znx_proc_init();

    if (!znx_core_conf_parse("/tmp/core_exp.yaml")) {
        if (g_core_conf) {
            ZNX_DEF_LOG_FATAL(NULL, "parse /tmp/core_exp.yaml failed, err: %v",
                &g_core_conf->err);
        }
        ZNX_DEF_LOG_FATAL(NULL, "parse /tmp/core_exp.yaml failed, err: unknow");
    }

    if (!znx_http_main_conf_parse((const char *)g_core_conf->http_main_conf_path.data)) {
        if (g_http_main_conf != NULL) {
            ZNX_DEF_LOG_FATAL(NULL, "parse %v failed, err: %v",
                &g_core_conf->http_main_conf_path, &g_http_main_conf->err);
        } else {
            ZNX_DEF_LOG_FATAL(NULL, "parse %v failed, err: unknow",
                &g_core_conf->http_main_conf_path);
        }
    }

    znx_modules_main_init_exec();

    if (g_core_conf->g_mem_freelists_level > 0) {
        znx_mem_init((size_t)g_core_conf->g_mem_freelists_level);
    }

    if (g_core_conf->g_aligned_mem_freelists_level > 0) {
        znx_mem_init((size_t)g_core_conf->g_aligned_mem_freelists_level);
    }

    if (g_http_main_conf->server_core_conf->read_request_header_timeout_ms != 100) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 100, but got %d",
            g_http_main_conf->server_core_conf->read_request_header_timeout_ms);
    }

    if (g_http_main_conf->server_core_conf->request_header_buf_size != 4096) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 4096, but got %d",
            g_http_main_conf->server_core_conf->request_header_buf_size);
    }

    if (g_http_main_conf->server_core_conf->max_request_header_size != 4096) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 4096, but got %d",
            g_http_main_conf->server_core_conf->max_request_header_size);
    }

    if (g_http_main_conf->proxy_core_conf->read_request_header_timeout_ms != 10000) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 10000, but got %d",
            g_http_main_conf->proxy_core_conf->read_request_header_timeout_ms);
    }

    if (g_http_main_conf->proxy_core_conf->request_header_buf_size != 8192) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 8192, but got %d",
            g_http_main_conf->proxy_core_conf->request_header_buf_size);
    }

    if (g_http_main_conf->proxy_core_conf->max_request_header_size != 8192) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 8192, but got %d",
            g_http_main_conf->proxy_core_conf->max_request_header_size);
    }

#if (ZNX_EXP_HTTP_MODULE)
    test_exp_http_module();
#endif

    test_http_site_conf_parse();

    znx_worker_processor_start(2, 0, 0);

    usleep(10000);

    znx_proc_shutdown();

    return 0;
}